﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using SlimDX;
using SlimDX.Direct3D9;

namespace Gype.UI.D3D9
{
    internal class SpriteFont : UI.SpriteFont
    {
        private Font mFont;
        private Sprite mFontSprite;
        private GdiFontProvider mFontProvider;

        public SpriteFont(Rendertarget9 target, Sprite fontSprite, string fontFamily, float pixelSize)
        {
            Target = target;
            mFontProvider = new GdiFontProvider(target, fontFamily, (int)pixelSize);

            mFont = new Font(fontSprite.Device, (int)pixelSize, 0, FontWeight.Normal, 1, false, CharacterSet.Default, Precision.TrueType, FontQuality.Antialiased, PitchAndFamily.Default, fontFamily);
            mFontSprite = fontSprite;
        }

        private DrawTextFormat GetTextFormat(TextAlignement textAlign, ParagraphAlignement paragraphAlign)
        {
            DrawTextFormat format = DrawTextFormat.SingleLine;
            switch (textAlign)
            {
                case TextAlignement.Center:
                    format |= DrawTextFormat.Center;
                    break;
                case TextAlignement.Left:
                    format |= DrawTextFormat.Left;
                    break;
                case TextAlignement.Right:
                    format |= DrawTextFormat.Right;
                    break;

                default:
                    throw new ArgumentException("textAlign");
            }

            switch (paragraphAlign)
            {
                case ParagraphAlignement.Bottom:
                    format |= DrawTextFormat.Bottom;
                    break;
                case ParagraphAlignement.Top:
                    format |= DrawTextFormat.Top;
                    break;
                case ParagraphAlignement.Center:
                    format |= DrawTextFormat.VerticalCenter;
                    break;
            }

            return format;
        }

        public override System.Drawing.SizeF MeasureString(string Text, Vector2 size)
        {
            var rect = mFontProvider.MeasureString(Text);
            float cx = rect.Right - rect.Left;
            float cy = rect.Bottom - rect.Top;

            float scale = 1;
            if (cx > size.X || cy > size.Y)
            {
                float scaleX = 1, scaleY = 1;
                if (cx > size.X)
                    scaleX = size.X / cx;
                if (cy > size.Y)
                    scaleY = size.Y / cy;

                float scaleMax = Math.Min(scaleX, scaleY);
                scale = scaleMax;
            }

            return new System.Drawing.SizeF(cx * scale, cy * scale);
        }

        public override System.Drawing.SizeF MeasureString(string text)
        {
            var rect = mFontProvider.MeasureString(text);
            return new System.Drawing.SizeF(rect.Right - rect.Left, rect.Bottom - rect.Top);
        }

        public override void DrawText(string text, Vector2 position, Vector2 size, TextElement elem)
        {
            var rect = mFontProvider.MeasureString(text);
            float cx = rect.Right - rect.Left;
            float cy = rect.Bottom - rect.Top;

            float scale = 1;
            if ((((elem.Flags & FontFlags.StretchToWidth) != 0) && cx > size.X) || ((elem.Flags & FontFlags.StretchToHeight) != 0 && cy > size.Y))
            {
                float scaleX = 1, scaleY = 1;
                if ((elem.Flags & FontFlags.StretchToWidth) != 0)
                    scaleX = size.X / cx;
                if ((elem.Flags & FontFlags.StretchToHeight) != 0)
                    scaleY = size.Y / cy;

                float scaleMax = Math.Min(scaleX, scaleY);
                scale = scaleMax;
            }

            if (elem.Height >= 0)
            {
                scale = elem.Height / cy;
            }

            switch (elem.Alignment)
            {
                case TextAlignement.Center:
                    {
                        position.X += size.X / 2.0f;
                        position.X -= cx * scale / 2.0f;
                    }
                    break;

                case TextAlignement.Right:
                    {
                        position.X += size.X;
                        position.X -= cx * scale;
                    }
                    break;

                case TextAlignement.Left:
                    break;
            }

            switch (elem.ParagraphAlignement)
            {
                case ParagraphAlignement.Top:
                    break;

                case ParagraphAlignement.Center:
                    position.Y += size.Y / 2.0f - cy * scale / 2.0f;
                    break;

                case ParagraphAlignement.Bottom:
                    position.Y += size.Y - cy * scale;
                    break;
            }

            mFontProvider.DrawString(text, position, size, FontFlags.BrushPerChar | elem.Flags, elem.Color as D3D9.Brush, scale);
            //mFont.DrawString(mFontSprite, text, new System.Drawing.Rectangle(0, 0, (int)(size.X / scale), (int)(size.Y / scale)), GetTextFormat(textAlign, paragraphs), color);
        }
    }
}
